﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using ICSharpCode.SharpZipLib.Zip;
using Newtonsoft.Json;


public class OssConfig
{
    public string bucket;
    public string end_point;
    public string cdn_url;
    public string access_key_id;
    public string access_key_secret;
    
    
}

class DeployExternalResourceWindow: EditorWindow
{
    public enum Platform
    {
        none,
        ios,
        android,
        total,
    }

    public enum CompileType
    {
        none,
        alpha,
        beta,
        release,
    }

    public enum SupportCompressType
    {
        NONE,
        LZMA,
    }

    const string PrefPrefix = "deploy_external_resource_window_";

    int version = -1;
    int min_app_version = 0;
    Platform platform;
    CompileType compileType = CompileType.alpha;
    SupportCompressType compressType = SupportCompressType.LZMA;
    bool enable = true;
    bool totalFiles = false;
    static string ext = "";
    bool debug = false;
    bool encodeLua = false;
    string adbPath;
    string packageName;
    string hostIp;

    static Dictionary<string, string> webServerInfos = null;
    public static string GetWebServerHost(string compileType)
    {
        if(webServerInfos == null)
        {
            TextAsset t = Resources.Load<TextAsset>("webserver");
            webServerInfos = JsonConvert.DeserializeObject<Dictionary<string, string>>(t.text);
        }

        return webServerInfos[compileType];
    }


    public static OssConfig GetOssConfig()
    {
        TextAsset asset = AssetDatabase.LoadAssetAtPath<TextAsset>("Assets/editor_config/oss_config.txt");
        return JsonConvert.DeserializeObject<OssConfig>(asset.text);

    }

    static void CommitToOss(string zipPath, int version, int min_app_version, Platform platform, CompileType compileType, string md5, bool enable, string scriptDir, string secretKey, OssConfig ossConfig)
    {
        string logOutput = null;
        string logOutputError = null;

        string cmd = scriptDir + "/commit_external_resource" + (Application.platform == RuntimePlatform.OSXEditor? ".sh": ".bat");
        string param = zipPath + " " + ossConfig.access_key_id + " " + ossConfig.access_key_secret + " " + ossConfig.end_point + " " + ossConfig.bucket + " " + CommonUtil.GetAppInfo().app_name + "/external_resource/" + platform + "/" + compileType + "/" + zipPath;
        Debug.Log(cmd + " " + param);

        int exitCode = CommandLineTool.CmdWithOutput(cmd, param, ref logOutput, ref logOutputError);

        if (exitCode != 0)
        {
            Debug.LogError(logOutputError);
            return;
        }


        DeployToDb(zipPath, version, min_app_version, platform, compileType, md5, enable, secretKey);

//        string paramStr = System.IO.Path.GetFileName(zipPath) + "  " + CommonUtil.GetFileSize(zipPath) + "  " + version + "  " + min_app_version + "  " + platform + "  " + compileType + "  " + md5 + "  " + enable;
//        err = CommandLineTool.cmdWithOutput("script/deploy_lua_zip" + (Application.platform == RuntimePlatform.OSXEditor? ".sh": ".bat"), paramStr, ref logOutput);
//        if (!string.IsNullOrEmpty(err))
//        {
//            Debug.LogError(err);
//        }
    }

    static bool DeployToDb(string zipPath, int version, int min_app_version, Platform platform, CompileType compileType, string md5, bool enable, string secretKey)
    {
        Dictionary<string, string> dic = new Dictionary<string, string>();
        dic.Add("app_name", CommonUtil.GetAppInfo().app_name);
        dic.Add("platform", platform.ToString());
        dic.Add("compile_type", compileType.ToString());
        dic.Add("version", version.ToString());
        dic.Add("min_app_version", min_app_version.ToString());
        dic.Add("file_name", System.IO.Path.GetFileName(zipPath));
        dic.Add("file_size", CommonUtil.GetFileSize(zipPath).ToString());
        dic.Add("md5", md5);
        dic.Add("enable", enable.ToString());
        dic.Add("secret_key", secretKey);

        string urlHost = GetWebServerHost(compileType.ToString());
        string tempUrl = HttpRequestManager.CombineUrlAndGetParameters(urlHost + "/resource/addExternalResourceVersion", dic);

        string logOutput = null;
        string logOutputError = null;
        string param = tempUrl + " --insecure";
        int exitCode = CommandLineTool.CmdWithOutput("curl", param, ref logOutput, ref logOutputError);
        Debug.Log("curl " + param);

        if (exitCode != 0)
        {
            Debug.LogError(logOutputError);
            return false;
        }
        return true;
    }

    static List<DeployExternalResourceWindow.NeedCompressDirInfo> GetDirInfos()
    {
        // List<string> luaDirs = new List<string>(LuaConst.luaDirs);
        // luaDirs.Add(LuaConst.toluaDir);

        // List<DeployExternalResourceWindow.NeedCompressDirInfo> luaDirInfos = new List<DeployExternalResourceWindow.NeedCompressDirInfo>();
        // {
        //     DeployExternalResourceWindow.NeedCompressDirInfo luaDirInfo = new DeployExternalResourceWindow.NeedCompressDirInfo();
        //     luaDirInfo.dirPaths = luaDirs.ToArray();
        //     luaDirInfo.prefix = LuaResLoader.luaDir + "/";
        //     luaDirInfos.Add(luaDirInfo);
        // }
        // {
        //     DeployExternalResourceWindow.NeedCompressDirInfo luaDirInfo = new DeployExternalResourceWindow.NeedCompressDirInfo();
        //     luaDirInfo.dirPaths = new string[]{ ResourcesEx.BundleResDir + "/" + LangManager.dir };
        //     luaDirInfo.prefix = LangManager.dir + "/";
        //     luaDirInfos.Add(luaDirInfo);
        // }
        // {
        //     DeployExternalResourceWindow.NeedCompressDirInfo luaDirInfo = new DeployExternalResourceWindow.NeedCompressDirInfo();
        //     luaDirInfo.dirPaths = new string[]{ ResourcesEx.BundleResDir + "/" + NotchInfoManager.dir };
        //     luaDirInfo.prefix = NotchInfoManager.dir + "/";
        //     luaDirInfos.Add(luaDirInfo);
        // }
        // {
        //     DeployExternalResourceWindow.NeedCompressDirInfo luaDirInfo = new DeployExternalResourceWindow.NeedCompressDirInfo();
        //     luaDirInfo.dirPaths = new string[]{ ResourcesEx.BundleResDir + "/" + SensitiveWordManager.dirName };
        //     luaDirInfo.prefix = SensitiveWordManager.dirName + "/";
        //     luaDirInfos.Add(luaDirInfo);
        // }
		// {
		// 	DeployExternalResourceWindow.NeedCompressDirInfo luaDirInfo = new DeployExternalResourceWindow.NeedCompressDirInfo();
		// 	luaDirInfo.dirPaths = new string[]{ ResourcesEx.BundleResDir + "/" + "json" };
		// 	luaDirInfo.prefix = "json" + "/";
		// 	luaDirInfos.Add(luaDirInfo);
		// }

        List<DeployExternalResourceWindow.NeedCompressDirInfo> luaDirInfos = CommonUtil.ObjectFromJsonFile<List<DeployExternalResourceWindow.NeedCompressDirInfo>>("Assets/BundleRes/external_resource_config.txt");

        return luaDirInfos;
    }

    static string CreateExternalResourcePackage(HashSet<string> modifiedFileSet, int version, SupportCompressType compressType, bool encodeLua, BuildTargetGroup platform, out string md5)
    {
        string outputPath = "lua_" + version + ext;

        List<DeployExternalResourceWindow.NeedCompressDirInfo> luaDirInfos = GetDirInfos();

        DeployExternalResourceWindow.BuildConfigPackage(luaDirInfos.ToArray(), modifiedFileSet, outputPath, encodeLua, platform, compressType == SupportCompressType.LZMA? CompressType.LZMA: CompressType.NONE);

        md5 = MD5Hash.GetMD5HashFromFile(outputPath);

        string newFilePath = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(outputPath), version + "_" + md5 + "_" + CommonUtil.GetFileSize(outputPath) + ext);
        CommonUtil.Move(outputPath, newFilePath);

        return newFilePath;
    }

    static HashSet<string> GetModifiedPathSet(int startSvnVersion, bool totalFiles)
    {
        HashSet<string> modifiedPaths = null;
        if (!totalFiles)
        {
            HashSet<string> modifiedPaths2 = SvnTool.GetModifiedFileSet(startSvnVersion);
            HashSet<string> currentModifiedPaths = SvnTool.GetCurrentModifiedFileSet();
            modifiedPaths2.Add(currentModifiedPaths);

            modifiedPaths = new HashSet<string>();
            foreach (var p in modifiedPaths2)
            {
                modifiedPaths.Add(p.Replace("\\", "/"));
            }
        }

        return modifiedPaths;
    }

    void CommitDebug(string packageName, string hostIp)
    {
        if (string.IsNullOrEmpty(adbPath))
        {
            Debug.LogError("adbPath is empty");
            return;
        }

        if (string.IsNullOrEmpty(packageName))
        {
            Debug.LogError("packageName is empty");
            return;
        }
            
        string adbPath2 = adbPath;
        if (!string.IsNullOrEmpty(hostIp))
        {
            {
                string logOutput = null;
                string logOutputError = null;
                int exitCode = CommandLineTool.CmdWithOutput(adbPath2, "tcpip 5555", ref logOutput, ref logOutputError);
                if (exitCode != 0)
                {
                    if (!string.IsNullOrEmpty(logOutputError) && !logOutputError.Contains("error: no devices/emulators found"))
                    {
                        Debug.LogError(logOutputError);
                        return;
                    }
                }
            }

            {
                string logOutput = null;
                string logOutputError = null;
                int exitCode = CommandLineTool.CmdWithOutput(adbPath2, "disconnect ", ref logOutput, ref logOutputError);
                if (exitCode != 0)
                {
                    Debug.LogError(logOutputError);
                    return;
                }
            }

            {
                string logOutput = null;
                string logOutputError = null;
                int exitCode = CommandLineTool.CmdWithOutput(adbPath2, "connect " + hostIp, ref logOutput, ref logOutputError);
                if (exitCode != 0)
                {
                    Debug.LogError(logOutputError);
                    return;
                }
            }
        }

        {
            string logOutput = null;
            string logOutputError = null;
            int exitCode = CommandLineTool.CmdWithOutput(adbPath2, "shell rm -rf /sdcard/Android/data/" + packageName + "/files/" + version, ref logOutput, ref logOutputError);
            if (exitCode != 0)
            {
                Debug.LogError(logOutputError);
                return;
            }
        }

        {
            string logOutput = null;
            string logOutputError = null;
            int exitCode = CommandLineTool.CmdWithOutput(adbPath2, "shell mkdir /sdcard/Android/data/" + packageName + "/files/" + version, ref logOutput, ref logOutputError);
            if (exitCode != 0)
            {
                Debug.LogError(logOutputError);
                return;
            }
        }

        List<DeployExternalResourceWindow.NeedCompressDirInfo> luaDirInfos = GetDirInfos();

        HashSet<string> modifiedPaths = GetModifiedPathSet(version, totalFiles);

        HashSet<string> createdDirSet = new HashSet<string>();
        DeployExternalResourceWindow.ForeachFile(luaDirInfos.ToArray(), modifiedPaths, (filePath, zipEntryPath) =>
            {
                string dir = System.IO.Path.GetDirectoryName(zipEntryPath);

//                if(!createdDirSet.Contains(dir))
//                {
//                    createdDirSet.Add(dir);
//
//                    string logOutput = null;
//                    string logOutputError = null;
//                    int exitCode = CommandLineTool.CmdWithOutput(adbPath2, "shell mkdir /sdcard/Android/data/" + packageName + "/files/" + version + "/" + dir, ref logOutput, ref logOutputError);
//                    if (exitCode != 0)
//                    {
//                        Debug.LogError(logOutputError);
//                        return;
//                    }
//                }

                {
                    string logOutput = null;
                    string logOutputError = null;
                    int exitCode = CommandLineTool.CmdWithOutput(adbPath2, "push " + filePath + " /sdcard/Android/data/" + packageName + "/files/" + version + "/" + zipEntryPath, ref logOutput, ref logOutputError);
                    if (exitCode != 0)
                    {
                        Debug.LogError(logOutputError);
                        return;
                    }
                }
            });


        if (!string.IsNullOrEmpty(hostIp))
        {
            {
                string logOutput = null;
                string logOutputError = null;
                int exitCode = CommandLineTool.CmdWithOutput(adbPath2, "disconnect", ref logOutput, ref logOutputError);
                if (exitCode != 0)
                {
                    Debug.LogError(logOutputError);
                    return;
                }
            }
        }
    }

    public static void CommitByCmd()
    {
        string[] args = System.Environment.GetCommandLineArgs();
        int version = 0;
        int minAppVersion = 0;
        Platform platform = Platform.none;
        CompileType compileType = CompileType.none;
        SupportCompressType compressType = SupportCompressType.NONE;
        bool totalFiles =false;
        bool encodeLua = true;
        bool enable = false;

        string scriptDir = null;
        string secretKey = null;
        OssConfig ossConfig = null;

        HashSet<string> modifiedSpriteSheetNames = new HashSet<string>();
        for (int i = 0; i < args.Length; i++)
        {
            if (args[i] == "-version") { version = int.Parse(args[i + 1]); i++; }
            if (args[i] == "-min_app_version") { minAppVersion = int.Parse(args[i + 1]); i++; }
            if (args[i] == "-platform") { platform = (Platform)System.Enum.Parse(typeof(Platform), args[i + 1]);  ; i++; }
            if (args[i] == "-compile_type") { compileType = (CompileType)System.Enum.Parse(typeof(CompileType), args[i + 1]); i++; }
            if (args[i] == "-compress_type") { compressType = (SupportCompressType)System.Enum.Parse(typeof(SupportCompressType), args[i + 1]); i++; }
            if (args[i] == "-total_files") { totalFiles = bool.Parse(args[i + 1]); i++; }
            if (args[i] == "-encode_lua") { encodeLua = bool.Parse(args[i + 1]); i++; }
            if (args[i] == "-enable") { enable = bool.Parse(args[i + 1]); i++; }
            if (args[i] == "-script_dir") { scriptDir = args[i + 1]; i++; }
            if (args[i] == "-secret_key") { secretKey = args[i + 1]; i++; }
            if (args[i] == "-oss_config")
            {
                string s = args[i + 1];
                i++;

                Debug.Log("oss_config: " + s);
                    
                string[] arr = s.Split('|');

                ossConfig = new OssConfig();
                ossConfig.bucket = arr[0];
                ossConfig.end_point = arr[1];
                ossConfig.cdn_url = arr[2];
                ossConfig.access_key_id = arr[3];
                ossConfig.access_key_secret = arr[4];
            }
        }


        Commit(version, minAppVersion, platform, compileType, compressType, totalFiles, encodeLua, enable, scriptDir, secretKey, ossConfig);
    }

    public static void Commit(int version, int minAppVersion, Platform platform, CompileType compileType, SupportCompressType compressType, bool totalFiles, bool encodeLua, bool enable, string scriptDir, string secretKey, OssConfig ossConfig)
    {
        HashSet<string> modifiedPaths = GetModifiedPathSet(minAppVersion, totalFiles);

        if (platform == Platform.total)
        {
            {
                string md5 = null;
                string luaPath = CreateExternalResourcePackage(modifiedPaths, version, compressType, encodeLua, BuildTargetGroup.Android, out md5);
                CommitToOss(luaPath, version, minAppVersion, Platform.android, compileType, md5, enable, scriptDir, secretKey, ossConfig);
                CommonUtil.Delete(luaPath);
            }
            {
                string md5 = null;
                string luaPath = CreateExternalResourcePackage(modifiedPaths, version, compressType, encodeLua, BuildTargetGroup.iOS, out md5);
                CommitToOss(luaPath, version, minAppVersion, Platform.ios, compileType, md5, enable, scriptDir, secretKey, ossConfig);
                CommonUtil.Delete(luaPath);
            }
        }
        else
        {
            string md5 = null;
            string luaPath = CreateExternalResourcePackage(modifiedPaths, version, compressType, encodeLua, platform == Platform.android? BuildTargetGroup.Android: BuildTargetGroup.iOS, out md5);
            CommitToOss(luaPath, version, minAppVersion, platform, compileType, md5, enable, scriptDir, secretKey, ossConfig);
            CommonUtil.Delete(luaPath);
        }
    }

    // void Commit(int tempMinAppVersion)
    // {
        // HashSet<string> modifiedPaths = GetModifiedPathSet(tempMinAppVersion, totalFiles);

        // if (platform == Platform.total)
        // {
        //     {
        //         string md5 = null;
        //         string luaPath = CreateExternalResourcePackage(modifiedPaths, encodeLua, BuildTargetGroup.Android, out md5);
        //         CommitToOss(luaPath, version, tempMinAppVersion, Platform.android, compileType, md5, enable);
        //         CommonUtil.Delete(luaPath);
        //     }
        //     {
        //         string md5 = null;
        //         string luaPath = CreateExternalResourcePackage(modifiedPaths, encodeLua, BuildTargetGroup.iOS, out md5);
        //         CommitToOss(luaPath, version, tempMinAppVersion, Platform.ios, compileType, md5, enable);
        //         CommonUtil.Delete(luaPath);
        //     }
        // }
        // else
        // {
        //     string md5 = null;
        //     string luaPath = CreateExternalResourcePackage(modifiedPaths, encodeLua, platform == Platform.android? BuildTargetGroup.Android: BuildTargetGroup.iOS, out md5);
        //     CommitToOss(luaPath, version, tempMinAppVersion, platform, compileType, md5, enable);
        //     CommonUtil.Delete(luaPath);
        // }
    // }

    void OnGUI()
    {
        if (version < 0)
        {
            version = PlayerPrefs.GetInt(PrefPrefix + "version", 0);
            min_app_version = PlayerPrefs.GetInt(PrefPrefix + "minAppVersion", 0);
            platform = (Platform)System.Enum.Parse(typeof(Platform), PlayerPrefs.GetString(PrefPrefix + "platform", platform.ToString()));
            compileType = (CompileType)System.Enum.Parse(typeof(CompileType), PlayerPrefs.GetString(PrefPrefix + "compileType", compileType.ToString()));
            compressType = (SupportCompressType)System.Enum.Parse(typeof(SupportCompressType), PlayerPrefs.GetString(PrefPrefix + "compressType", compressType.ToString()));
            enable = PlayerPrefsX.GetBool(PrefPrefix + "enable", enable);
            totalFiles = PlayerPrefsX.GetBool(PrefPrefix + "totalFiles", totalFiles);
            encodeLua = PlayerPrefsX.GetBool(PrefPrefix + "encodeLua", debug);
            debug = PlayerPrefsX.GetBool(PrefPrefix + "debug", debug);
            adbPath = PlayerPrefs.GetString(PrefPrefix + "adbPath", adbPath);
            packageName = PlayerPrefs.GetString(PrefPrefix + "packageName", packageName);
            hostIp = PlayerPrefs.GetString(PrefPrefix + "hostIp", hostIp);
        }

        version = EditorGUILayout.IntField("version: ", version);
        min_app_version = EditorGUILayout.IntField("minAppVersion: ", min_app_version);

        platform = (Platform)EditorGUILayout.EnumPopup("platform: ", platform);
        CompileType tempCompileType = (CompileType)EditorGUILayout.EnumPopup("compileType: ", compileType);
        if (tempCompileType != compileType)
        {
            compileType = tempCompileType;
            enable = compileType == CompileType.alpha;
            encodeLua = compileType == CompileType.release;
        }

        compressType = (SupportCompressType)EditorGUILayout.EnumPopup("compressType: ", compressType);
        totalFiles = GUILayout.Toggle(totalFiles, "totalFiles");
        encodeLua = GUILayout.Toggle(encodeLua, "encodeLua");
        enable = GUILayout.Toggle(enable, "enable");

//        if (Application.platform == RuntimePlatform.OSXEditor)
        {
            debug = GUILayout.Toggle(debug, "debug");
            if (debug)
            {
                adbPath = EditorGUILayout.TextField("adbPath: ", adbPath);
                packageName = EditorGUILayout.TextField("packageName: ", packageName);
                hostIp = EditorGUILayout.TextField("hostIp: ", hostIp);
            }
        }

        if (GUILayout.Button("Deploy"))
        {
            int tempMinAppVersion = min_app_version;
            if (tempMinAppVersion <= 0)
            {
                tempMinAppVersion = version;
            }

            string info = "";
            info += "version: " + version  + "\n";
            info += "minAppVersion: " + tempMinAppVersion  + "\n";
            info += "platform: " + platform  + "\n";
            info += "compileType: " + compileType  + "\n";
            info += "totalFiles: " + totalFiles  + "\n";
            info += "enable: " + enable  + "\n";
            info += "encodeLua: " + encodeLua  + "\n";

            string content = "Deploy " + platform + " " + compileType + "?";
            if (EditorUtility.DisplayDialog(content, info + "\n" + content, "OK", "Cancel"))
            {
                PlayerPrefs.SetInt(PrefPrefix + "version", version);
                PlayerPrefs.SetInt(PrefPrefix + "minAppVersion", min_app_version);
                PlayerPrefs.SetString(PrefPrefix + "platform", platform.ToString());
                PlayerPrefs.SetString(PrefPrefix + "compileType", compileType.ToString());
                PlayerPrefs.SetString(PrefPrefix + "compressType", compressType.ToString());
                PlayerPrefsX.SetBool(PrefPrefix + "enable", enable);
                PlayerPrefsX.SetBool(PrefPrefix + "totalFiles", totalFiles);
                PlayerPrefsX.SetBool(PrefPrefix + "encodeLua", encodeLua);
                PlayerPrefsX.SetBool(PrefPrefix + "debug", debug);
                PlayerPrefs.SetString(PrefPrefix + "adbPath", adbPath);
                PlayerPrefs.SetString(PrefPrefix + "packageName", packageName);
                PlayerPrefs.SetString(PrefPrefix + "hostIp", hostIp);
                
                PlayerPrefs.Save();
                
                if(platform == Platform.none)
                {
                    return;
                }

                if (debug)
                {
                    CommitDebug(packageName, hostIp);
                }
                else
                {
                    var ossConfig = GetOssConfig();
                    Commit(version, tempMinAppVersion, platform, compileType, compressType, totalFiles, encodeLua, enable, "../jenkins_script", "", ossConfig);
                }
            }
        }
    }

    [MenuItem("Custom/Window/DeployExternalResource")]
    public static void Open()
    {
        DeployExternalResourceWindow myWindow = (DeployExternalResourceWindow)EditorWindow.GetWindow(typeof(DeployExternalResourceWindow), false, "DeployExternalResource", true);
        myWindow.Show();
    }

    public class NeedCompressDirInfo
    {
        public string[] dirPaths;
        public string prefix;
        public string[] prefixs;
    }

    public static void ForeachFile(NeedCompressDirInfo[] dirInfos, HashSet<string> modifiedFileSet, System.Action<string, string> callback)
    {
        string[] onlyExts = new string[]{".lua", ".txt", ".bytes"};

        HashSet<string> luaPaths = new HashSet<string>();

        Dictionary<string, HashSet<string>> zipEntryMap = new Dictionary<string, HashSet<string>>();

        string projectDir = System.IO.Path.GetDirectoryName(Application.dataPath);

        for (int i = 0; i < dirInfos.Length; i++)
        {
            NeedCompressDirInfo dirInfo = dirInfos[i];

            for (int k = 0; k < dirInfo.dirPaths.Length; k++)
            {
                string srcDir = dirInfo.dirPaths[k];
                string[] filePaths = System.IO.Directory.GetFiles(srcDir, "*", System.IO.SearchOption.AllDirectories);
                for (int j = 0; j < filePaths.Length; j++)
                {
                    string filePath = filePaths[j];

                    filePath = filePath.Replace(projectDir + "/", "").Replace("\\", "/");

                    if (modifiedFileSet != null)
                    {
                        if (!modifiedFileSet.Contains(filePath))
                        {
                            continue;
                        }
                    }

                    if (filePath.EndsWith(".meta"))
                    {
                        continue;
                    }

                    if (System.IO.Path.GetFileName(filePath).StartsWith("."))
                    {
                        continue;
                    }

                    string ext = System.IO.Path.GetExtension(filePath);
                    int foundIndex = System.Array.FindIndex(onlyExts, (a) =>
                        {
                            return ext == a;
                        });

                    if (foundIndex < 0)
                    {
                        continue;
                    }

                    string zipEntryPath = filePath.Replace(srcDir, "");
                    if (!zipEntryPath.ToLower().EndsWith(".lua"))
                    {
                        int index = zipEntryPath.LastIndexOf(".");
                        if (index < 0)
                        {
                            continue;
                        }

                        zipEntryPath = zipEntryPath.Substring(0, index);
                    }
//                    else
//                    {
//                        Debug.LogError("sadf: " + filePath);
//                    }

                    if (zipEntryPath.StartsWith("/"))
                    {
                        zipEntryPath = zipEntryPath.Substring(1, zipEntryPath.Length - 1);
                    }

                    
                    if(dirInfo.prefix != null)
                    {
                        string zipEntryPath2 = dirInfo.prefix + "/" + zipEntryPath;
                        luaPaths.Add(filePath);

                        HashSet<string> outputPaths = null;
                        if(!zipEntryMap.TryGetValue(filePath, out outputPaths))
                        {
                            outputPaths = new HashSet<string>();
                            zipEntryMap.Add(filePath, outputPaths);
                        }
                        outputPaths.Add(zipEntryPath2);
                    }


                    if(dirInfo.prefixs != null)
                    {
                        luaPaths.Add(filePath);

                        for(int t = 0; t < dirInfo.prefixs.Length; t++)
                        {
                            string zipEntryPath2 = dirInfo.prefixs[t] + "/" + zipEntryPath;

                            HashSet<string> outputPaths = null;
                            if(!zipEntryMap.TryGetValue(filePath, out outputPaths))
                            {
                                outputPaths = new HashSet<string>();
                                zipEntryMap.Add(filePath, outputPaths);
                            }
                            outputPaths.Add(zipEntryPath2);
                        }
                    }
                }
            }
        }


        List<string> luaPathList = new List<string>(luaPaths);
        luaPathList.Sort();

        for (int i = 0; i < luaPathList.Count; i++)
        {
            string filePath = luaPathList[i];
            HashSet<string> zipEntryPaths = zipEntryMap[filePath];
            foreach(var p in zipEntryPaths)
            {
                callback(filePath, p);
            }
        }
    }

    public static void BuildConfigPackage(NeedCompressDirInfo[] dirInfos, HashSet<string> modifiedFileSet, string outputPath, bool encodeLua, BuildTargetGroup platform, uint compressType)
    {
        List<ExternalResourcePackageFileInfo> fileInfoList = new List<ExternalResourcePackageFileInfo>();
        System.IO.MemoryStream ms = new System.IO.MemoryStream();
        // bool first = true;

        string log = "deployed files:\n";
        ForeachFile(dirInfos, modifiedFileSet, (filePath, zipEntryPath) =>
            {
                log += filePath + "\n";
                byte[] data = null;
               if (encodeLua && System.IO.Path.GetExtension(filePath.ToLower()) == ".lua")
               {
                   string tempPath = System.IO.Path.GetTempFileName();
                   
                   Packager.Cpu cpu = filePath.Contains("/64/")? Packager.Cpu._64: Packager.Cpu._32;

                   string error = Packager.EncodeLuaFile(platform, cpu, System.IO.Path.GetFullPath(filePath), tempPath);
                   if (!string.IsNullOrEmpty(error))
                   {
                       Debug.LogError(error);
                   }

                   data = CommonUtil.fileToBytes(tempPath);
               }
               else
                {
                    data = CommonUtil.fileToBytes(filePath);
                }

                if(data == null || data.Length <= 0)
                {
                    if(CommonUtil.GetFileSize(filePath) > 0)
                    {
                        throw new System.Exception("data is null or data's length is 0: " + filePath + "  " + encodeLua  + "  " + System.IO.File.Exists(filePath) + "  " + System.Environment.CurrentDirectory);
                    }
                }

                ExternalResourcePackageFileInfo fileInfo = new ExternalResourcePackageFileInfo();
                fileInfo.fileName = zipEntryPath;
                fileInfo.originalLength = data.Length;
                fileInfo.begin = (int)ms.Position;

                byte[] compressedData = null;
                if (!CompressManager.CompressBytes(compressType, data, out compressedData))
                {
                    throw new System.Exception("compress data failed: " + filePath + "  " + compressType);
                }

                fileInfo.length = compressedData.Length;
                fileInfoList.Add(fileInfo);

                ms.Write(compressedData, 0, compressedData.Length);
            });

        ExternalResourcePackageInfo info = new ExternalResourcePackageInfo();
        info.compressType = (byte)compressType;
        info.fileInfos = fileInfoList.ToArray();

        byte[] data2 = ms.ToArray();

        ms.Position = 0;
        ms.SetLength(0);
        System.IO.BinaryWriter writer = new System.IO.BinaryWriter(ms);
        info.Write(writer);
        byte[] headerData = ms.ToArray();

        System.IO.FileStream outFs = new System.IO.FileStream(outputPath, System.IO.FileMode.Create);
        outFs.Write(headerData, 0, headerData.Length);
        outFs.Write(data2, 0, data2.Length);
        outFs.Close();

        Debug.Log(log);

        //        System.IO.BinaryReader reader = new System.IO.BinaryReader(new System.IO.MemoryStream(headerData));
        //        LuaPackageInfo ii = new LuaPackageInfo();
        //        ii.Read(reader);
        //
        //        Debug.LogError("asdf: " + ii.fileInfos.Length);

        //        CommonUtil.bytesToFile(outputPath, data2);
    }
}